import Logic from '../../js/htmls/logic/logic.mjs';
import { defineAsyncComponent, toRaw, nextTick, resolveComponent } from 'vue';
let idGen = 0;
let DebugView = defineAsyncComponent(() => {
    function emptyDebuggingVMState() {
        return {
            FSMs: [],
            stack: [],
            displayFSM: -1,
            selectedFrame: null,
            frameDetial: {}
        };
    };
    return new Promise((resolve) => {
        fetch('./components/DebugView/DebugView.html').then((res) => res.text()).then(async (template) => {

            let link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = './components/DebugView/DebugView.css';
            document.head.appendChild(link);


            resolve({
                name: 'DebugView',
                props: ['style', 'sendMessage', 'scene'],
                template,
                data() {
                    return {
                        paused: false,
                        breakpointsEnabled: true,
                        id: 'DebugView-' + (idGen++),
                        debuggingVMState: emptyDebuggingVMState(),
                        workspaceTab: null
                    };
                },
                methods: {
                    async gotoBlock(frame, idx) {
                        let inst = JSON.parse(frame);
                        let [blockId, codename, src, fsm, state] = inst;
                        let tab;
                        if (!fsm) {
                            tab = await Logic.instance.openFunction(src, codename, blockId);
                        } else if (!state) {
                            tab = await Logic.instance.openActionGroup(src, fsm, codename, blockId);
                        } else {
                            tab = await Logic.instance.openState(src, fsm, state, blockId);
                        }
                        this.workspaceTab = tab;
                        if (typeof (idx) == 'number') {
                            this.debuggingVMState.selectedFrame = frame;
                            this.sendMessage({ 'cmd': 'debug', method: "getStackDetial", args: [idx] });
                        }
                    },
                    togglePause() {
                        // this.paused = !this.paused;
                        if (this.paused) {
                            this.sendMessage({ 'cmd': 'debug', method: "resume" });
                        } else {
                            this.sendMessage({ 'cmd': 'debug', method: "pause" });
                        }
                    },
                    onVMPaused() {
                        this.paused = true;
                        let listFSMCmd = { 'cmd': 'debug', method: "listFSM" };
                        this.sendMessage(listFSMCmd);
                    },
                    onlistFSM_reply(list) {
                        this.debuggingVMState.FSMs = list;
                        let brokens = list.filter(x => x.broken);
                        if (brokens.length > 0) {
                            this.sendMessage({ 'cmd': 'debug', method: "getStack", args: [brokens[0].id] });
                        }
                    },
                    frameToDisplay(frame) {
                        let inst = JSON.parse(frame);
                        let str = '';
                        if (inst[2]) {
                            str += '.' + inst[2];
                        }
                        if (inst[3]) {
                            str += '.' + inst[3];
                        }
                        str += '.' + inst[1];
                        return str.substring(1);
                    },
                    ongetStack_reply(id, stack) {
                        this.debuggingVMState.stack = stack;
                        this.debuggingVMState.displayFSM = id;
                        let idx = stack.length - 1;
                        this.debuggingVMState.selectedFrame = stack[idx].inst;
                        this.gotoBlock(this.debuggingVMState.selectedFrame, idx);
                    },
                    onVMResumed() {
                        this.debuggingVMState = emptyDebuggingVMState();
                        this.paused = false;
                    },
                    fillBlockInfo(block, stack) {
                        if (block) {
                            stack.text = block.toString().substring(0, 15);
                            stack.ASTType = block.outputConnection?.check[0];
                            if (stack.ASTType == 'Boolean') {
                                stack.valueText = stack[2] == 1 ? OpenBlock.i('LOGIC_BOOLEAN_TRUE') : OpenBlock.i('LOGIC_BOOLEAN_FALSE');
                            } else if (OpenBlock.Struct.baseTypes.includes(stack.ASTType)) {
                                stack.valueText = stack[2];
                            } else {
                                stack.valueText = stack.ASTType;
                            }
                        }
                    },
                    ongetStackDetial_reply(frameIdx, frameDetial) {
                        this.debuggingVMState.frameDetial = frameDetial;
                        frameDetial.forEach(stack => {
                            let blockId = JSON.parse(stack[0])[0];
                            let block = this.workspaceTab.content.context.workspace.getBlockById(blockId);
                            this.fillBlockInfo(block, stack);
                        });
                        this.debuggingVMState.stack.forEach(stack => {
                            let inst = JSON.parse(stack.inst);
                            let [blockId, codename, src, fsm, state] = inst;
                            let workspace = this.workspaceTab.content.context.workspace;
                            if (codename != workspace._openblock_env?._openblock_target.name) {
                                return;
                            }
                            if (src != workspace._openblock_env?._openblock_src.name) {
                                return;
                            }
                            let block = workspace.getBlockById(blockId);
                            this.fillBlockInfo(block.getRootBlock(), stack);
                        });
                        this.workspaceTab = null;
                    },
                    debug(name, args, level, stack, block) {
                        let method = 'on' + name;
                        if (this[method]) {
                            this[method].apply(this, args);
                        }
                    }
                },
                mounted() {
                },
                beforeUnmount() {
                }
            });
        });
    });
});
export default DebugView;